// 状态管理库
import {create} from "zustand";
// 包装状态管理库 实现将状态信息存入浏览器
import {persist} from "zustand/middleware";

import {DialogType, Message, MessageDirection, MessageRole, MessageType, SessionConfig} from "@/types/chat";
import {GLMVersion, GptVersion} from "@/app/constants";
import {completions} from "@/apis/index"
import {useState} from "react";

// 聊天信息存储接口
interface ChatStore {
    id: number;
    // 对话Session 包括对话框和聊天内容
    sessions: ChatSession[];
    // 当前索引值
    currentSessionIndex: number;
    // 打开对话Session 是一个回调函数
    openSession: (title: string, description: string) => ChatSession;
    // 选中一个对话Session
    selectSession: (index: number) => void;
    // 删除一个对话Session
    deleteSession: (index: number) => void;
    // 当前Session
    currentSession: () => ChatSession;
    // 发送消息
    onSendMessage: (message: Message) => Promise<void>;
    // 更新当前聊天Session
    updateCurrentSession: (updater: (session: ChatSession) => void) => void;
    // 重试
    onRetry: () => void;
    // 停止
    onSessionStop: () => void;

}
export interface ChatSession {
    // 标识当前会话是否停止
    isSessStop: boolean,
    // 会话ID
    id: number;
    // 对话框
    dialog: DialogType;
    // 对话消息
    messages: Message[];
    // 会话模型配置
    config: SessionConfig;
    // 清除会话的索引
    clearContextIndex?: number;
    // 输入框是否禁用
    isDisabled: boolean
}

export function createNewMessage(value: string, role?: MessageRole) {
    return {
        avatar: role !== MessageRole.user ? "/role/wali.png" : "/role/user_2.png",
        content: value,
        time: Date.now(),
        role: role || MessageRole.user,
        isStop : false
    } as Message;
}

// 格式化消息
function formatMessage(messages: Message[]) {

    //3表示从数组末尾开始倒数第三个元素，如果数组长度不够，则截取全部元素
    const latestMessages = messages.length > 3 ? messages.slice(-3) : messages
    // 对每个元素解构获取content和role属性，并返回一个新的数组，每个元素包含content和role属性。
    return latestMessages.map(({content, role}) => ({
        content,
        role,
    }))
}

function createChatSession(title: string, description: string): ChatSession {
    return {
        id: 0,
        dialog: {
            avatar: "/role/wali.png",
            title: title || "新的对话",
            count: 0,
            subTitle: description || "请问有什么需要帮助的吗？",
            timestamp: new Date().getTime(),

        },
        messages: [
            {
                avatar: "/role/wali.png",
                content: description || "请问有什么需要帮助的吗？",
                message_type: MessageType.Text,
                time: Date.now(),
                direction: MessageDirection.Receive,
                role: MessageRole.system,
                isStop: false
            }
        ],
        config: {
            glmConfig: GLMVersion.CHATGLM_TURBO,
            gptVersion: GptVersion.GPT_3_5_TURBO,
            huiHuaFlag: 1
        },
        clearContextIndex: undefined,
        isDisabled: false,
        isSessStop:false

    }

}

// create 函数来自于 Zustand 状态管理库 用于创建一个新的状态仓库。这个仓库存储在内存中，而不是将状态信息存储到具体的地方，比如浏览器的本地存储或服务器。
// persist 中间件，它允许你将状态信息持久化到浏览器的本地存储中，以便在页面刷新后能够恢复之前的状态。
// persist 函数将状态仓库包装起来实现的。

export const userChatStore = create<ChatStore>()(

    persist(
        (set, get) => ({
            id: 0,
            sessions: [createChatSession('', '')],
            currentSessionIndex: 0,
            openSession(title: string, description: string) {
                const session = createChatSession(title, description);
                // set 是 Zustand 提供的用于更新状态的函数。这里使用的 id 仅仅是用于在状态中标识不同的会话，并不一定要和实际的聊天会话对象中的 id 对应。
                set(() => ({id: get().id + 1}))
                session.id = get().id
                // 保存创建的会话到Session数组中
                set(state => (
                    {
                        currentSessionIndex: session.id,
                        sessions: [session].concat(state.sessions),
                    }
                ))
                return session;
            },
            // 选择会话
            selectSession(index: number) {
                set({
                    currentSessionIndex: index,
                });
            },
            // 删除会话
            deleteSession(index: number) {
                // 获取当前状态中会话数组的长度，即当前会话的数量
                const count = get().sessions.length;
                // 获取指定索引位置的会话对象
                const deleteSession = get().sessions.at(index);
                // 如果 deleteSession 不存在（为 null 或 undefined），则直接返回
                if (!deleteSession) return;
                // 复制当前状态中的会话数组
                const sessions = get().sessions.slice();
                // 删除指定索引位置的会话
                sessions.splice(index, 1);
                // 删除聊天会话时 调整当前选中的会话索引
                const currentIndex = get().currentSessionIndex;
                let nextIndex = Math.min(
                    currentIndex - Number(index < currentIndex),
                    sessions.length - 1,
                );
                // 删除后只剩下一个会话，那么需要重新创建一个空白的会话，并将其添加到会话数组中，
                // 同时将 nextIndex 设置为 0，即新创建的空白会话成为选中的会话
                if (count === 1) {
                    nextIndex = 0;
                    sessions.push(createChatSession('', ''));
                }
                // 更新会话的状态
                set(() => ({
                    currentSessionIndex: nextIndex,
                    sessions,
                }));

            },
            // 当前会话
            currentSession() {
                let index = get().currentSessionIndex;
                const sessions = get().sessions;
                if (index < 0 || index >= sessions.length) {
                    index = Math.min(sessions.length - 1, Math.max(0, index));
                    set(() => ({currentSessionIndex: index}));
                }
                return sessions[index];
            },
            async onSendMessage(message: Message) {
                const session = get().currentSession();
                get().updateCurrentSession((session) => {
                    // session.messages 数组的末尾添加了一个新的元素 message。 返回一个新的数组
                    session.messages = session.messages.concat(message)
                    // 更新subTitle
                    session.dialog.subTitle = message.content;
                });
                session.isDisabled = true
                // todo 后续可以调用服务端 完成问答
                // 1、调用之前回传历史消息 可以完成上下文对话
                const activeMessages = session.messages
                    .filter(msg => msg.role !== MessageRole.system)
                    .slice(session.clearContextIndex || 0);
                // 格式化（回传最大消息不能超过三条）
                const messages = formatMessage(activeMessages);
                // 2、定义ReadableStream 用于接收服务端回传的消息
                const botMessage = createNewMessage("", MessageRole.system)
                get().updateCurrentSession((session) => {
                    session.messages = session.messages.concat(botMessage);
                });
                // 3、调用服务端 完成问答
                try {
                    // todo 2代表GPT 由于服务端还未完成 所以先使用 1 进行测试
                    // if (session.config.huiHuaFlag === 2) {
                    //     botMessage.content = "ChatGPT` 接口尚未对接，暂时还不能回复,请使用GLM **！！！**";
                    //     get().updateCurrentSession((session) => {
                    //         session.messages = session.messages.concat();
                    //         session.isDisabled = false
                    //     });
                    //     return
                    //
                    // }
                    console.log("会话标识：",session.config.huiHuaFlag)
                    console.log("会话标识：",session.config)
                    console.log("会话模型：",session.config.huiHuaFlag === 1 ?session.config.glmConfig :session.config.gptVersion)
                    // todo 根据选择的 radio 传递不同的参数 暂未处理 默认是 GLM
                    const {body} = await completions({
                        model: session.config.huiHuaFlag === 1 ?session.config.glmConfig :session.config.gptVersion,
                        messages: messages,
                        huiHuaFlag: session.config.huiHuaFlag
                    });
                    const reader = body!.getReader()
                    // 使用TextDecoder解码一个可读流
                    const decoder = new TextDecoder();
                    new ReadableStream({
                        start(controller) {
                            async function push() {
                                // done = true 读取结束
                                const {done, value} = await reader.read();
                                if (done) {
                                    controller.close();
                                    get().updateCurrentSession((session) => {
                                        session.isDisabled = false
                                        botMessage.isStop = false
                                        session.isSessStop = false
                                    });
                                    return;
                                }
                                if(!session.isSessStop ){ // 写入的时候判断 是否触发了停止操作
                                    controller.enqueue(value);
                                    // 解码
                                    const text = decoder.decode(value);
                                    botMessage.content += text;
                                    botMessage.isStop = true
                                    // 回传消息内容
                                    get().updateCurrentSession((session) => {
                                        session.messages = session.messages.concat();

                                    });
                                }else{
                                    get().updateCurrentSession((session) => {
                                        session.isDisabled = false
                                        botMessage.isStop = false
                                    });
                                }
                                // 递归 调用 相当于是循环
                                push();
                            }
                            push()
                        },
                    })
                } catch (error) {
                    console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>>>>>>>>")
                    console.log(error)
                    botMessage.content += "请求超时，请重新发送请求";
                    botMessage.isStop = false
                    // 回传消息内容
                    get().updateCurrentSession((session) => {
                        session.messages = session.messages.concat();
                        session.isDisabled = false
                        session.isSessStop = false
                    });

                }


            },
            onSessionStop() {
                console.log('停止~~~~~')
                get().updateCurrentSession((session) => {
                    session.isSessStop = true
                });

            },
            // 重试
            onRetry() {
                console.log('重试~~~~~')
                const session = get().currentSession();
                const activeMessages = session.messages?.slice(session.clearContextIndex || 0);
                const messages = formatMessage(activeMessages);
                // completions({messages, model: session.config.glmConfig});
            },


            updateCurrentSession(updater) {
                const sessions = get().sessions;
                const index = get().currentSessionIndex;
                // 调用updater函数，传入当前会话ChatSession对象
                updater(sessions[index]);
                set(() => ({sessions}))

            }

        }),
        {
            name: "chat-store-ghl"
        }
    ),
);
























